#include "workthread.h"
#include <QDebug>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <string.h>
#include <time.h>
#include "execsql.h"

#define SPEED B9600
#define PORT "/dev/ttyS0"
#define BUFF_MAXSIZE 100
extern QString testerAccount;//声明外部变量
typedef unsigned char un_char;

workthread::workthread()
{
    qDebug() << "workthread::workthread()";
}

int workthread::htoi(char s[])
{
    int totalNum = 0;
    int c;
    int position = 0;
    //int lastChar;
    c = s[position];
    while(c != '\0' && c > 0)
    {
        position++;
        c = s[position];
    }
    int total = --position;
    for(c = s[position]; position >= 0; position--)
    {
        int num = 0;
        c = s[position];
        //大写A～F转成数字10~15,数字字符转数字0～9
        if(c >= 'A' && c <= 'F')
        {
            num = c - 'A' + 10;
        }
        else
        {
            num = c - '0';
        }
        int exponent = total - position;
        int exponentNum = 1;
        for(; exponent > 0; exponent--)
        {
            exponentNum *= 16;
        }
        num *= exponentNum;
        totalNum += num;
    }
    return totalNum;
}

int workthread::init_serial()
{
    int fd = -1;
    struct termios tio;
    fd = open(PORT, O_RDWR | O_NOCTTY);
    if(fd < 0)
    {
        perror("InitSerial:open port error");
        return -1;
    }

    tcgetattr(fd,&tio);
    cfsetispeed(&tio,SPEED);	//串口输出波特率
    cfsetospeed(&tio,SPEED);	//串口输出波特率
    tio.c_cflag |= CLOCAL | CREAD;	//控制模式，保证程序不会成为端口的占有者，使能端口读取输入的数据
    tio.c_cflag &= ~PARENB;		//无奇偶校验位
    tio.c_cflag &= ~CSTOPB;		//设置停止位
    tio.c_cflag &= ~CSIZE;		//在设置数据位时，必须先使用CSIZE做屏蔽位
    tio.c_cflag |=	  CS8;		//设置数据位
    tio.c_iflag &= ~(IXON | IXOFF | IXANY);		//输入模式
    tio.c_cc[VTIME] = 0;		//设置等待时间
    tio.c_cc[VMIN] = 0;		//设置最小接收字符
    tio.c_lflag &= ~(ICANON | ECHO | ECHOE);	//本地模式
    tio.c_oflag &= ~OPOST;		//设置输出模式，原始数据输出
    tcflush(fd,TCIFLUSH);		//处理未接收字符,用于清空输入缓冲区
    if((tcsetattr(fd,TCSAFLUSH,&tio)) != 0)		//激活配置
    {
        perror("com set error");
    }
    else
    {
        printf("set done\n");
    }

    return fd;
}

int workthread::write_data(int fd, void *buf, int len)
{
    int len_w = write(fd,(un_char *)buf,len);
    if (len_w < 0)
    {
        printf("write data error\n");
        return -1;
    }
    return len_w;
}

int workthread::read_data(int fd, void *buf, int len)
{
    int len_r = read(fd,(un_char *)buf,len);
    if(len_r < 0)
    {
        printf("read error\n");
        return -1;
    }
    return len_r;
}

int workthread::test(int fd,QString& xldl,QString& jddz,QString& jnjg)
{
    int total = 0;
    int len = 0;
    int count=0;    //用于记录获取数据的次数
    un_char buff[BUFF_MAXSIZE];

    un_char buff_test[BUFF_MAXSIZE] = {0x7B,0x07,0x00,0x01,0x00,0x08,0x7D};
    len = write_data(fd,buff_test,7);

    sleep(5);
    un_char buff_result[BUFF_MAXSIZE] = {0x7B,0x07,0x00,0x04,0x00,0x0B,0x7D};
    len = write_data(fd,buff_result,7);
    len = 0;
    tcflush(fd,TCIFLUSH);		//处理未接收字符,用于清空输入缓冲区
    sleep(1);
    count=0;
    while(len == 0)
    {
        QString tep("接地测试等待数据");
        emit MsgSignal(tep);
        printf("---等待数据---\n");
        len = read_data(fd,buff,BUFF_MAXSIZE);
//        sleep(1);
        count++;
        if(count >= 10)
        {
            //如果十次仍未获取到数据，退出
            break;
        }
    }

    char c[2];
    sprintf(&c[0],"%x",buff[10] >> 4);
    sprintf(&c[1],"%x",buff[10]&0xf);
    if(c[0] == 'c' && c[1] == '1')
    {
        int i;
        char str[4];
        char dstr[5];
        for(i = 0; i < 2; ++i)
        {
            str[2*i] = buff[15+i] >> 4;
            str[2*i+1] = buff[15+i]&0xf;
        }

        sprintf(&dstr[0],"%X/n",str[2]);
        sprintf(&dstr[1],"%X/n",str[3]);
        sprintf(&dstr[2],"%X/n",str[0]);
        sprintf(&dstr[3],"%X/n",str[1]);
        dstr[4] = '\0';

        dianzuDetails = QString("接地测试合格 电阻:%1mΩ").arg(htoi(dstr));    //接地电阻合格
        emit MsgSignal(dianzuDetails);

//        jddz = QString::number(htoi(dstr));
        jddz = QString("PASS");
        printf("合格\n");
        printf("接地电阻 = %dmΩ\n",htoi(dstr));
        total += 1;
    }
    else
    {
        emit MsgSignal(QString("接地测试不合格"));
        printf("不合格\n");
        slot_stopTest();
    }


    sleep(6);
    un_char buff_result3[BUFF_MAXSIZE] = {0x7B,0x07,0x00,0x04,0x01,0x0C,0x7D};
    len = write_data(fd,buff_result3,7);
    len = 0;
    tcflush(fd,TCIFLUSH);		//处理未接收字符,用于清空输入缓冲区
    sleep(1);
    count=0;
    while(len == 0)
    {
        QString tep("泄露测试等待数据");
        emit MsgSignal(tep);
        printf("---等待数据---\n");
        len = read_data(fd,buff,BUFF_MAXSIZE);
//        sleep(1);
        count++;
        if(count >= 10)
        {
            //如果十次仍未获取到数据，退出
            break;
        }
    }

    sprintf(&c[0],"%x",buff[10] >> 4);
    sprintf(&c[1],"%x",buff[10]&0xf);
    if(c[0] == 'c' && c[1] == '1')
    {
        int i;
        char str[8];
        char dstr[9];
        for(i = 0; i < 4; ++i)
        {
            str[2*i] = buff[15+i] >> 4;
            str[2*i+1] = buff[15+i]&0xf;
        }

        sprintf(&dstr[0],"%X/n",str[6]);
        sprintf(&dstr[1],"%X/n",str[7]);
        sprintf(&dstr[2],"%X/n",str[4]);
        sprintf(&dstr[3],"%X/n",str[5]);
        sprintf(&dstr[4],"%X/n",str[2]);
        sprintf(&dstr[5],"%X/n",str[3]);
        sprintf(&dstr[6],"%X/n",str[0]);
        sprintf(&dstr[7],"%X/n",str[1]);
        dstr[8] = '\0';

        loudianDetails = QString("泄露测试合格 电流:%1mA").arg(htoi(dstr)/10000.00);
        emit MsgSignal(loudianDetails);

//        xldl = QString::number(htoi(dstr)/10000.00);
        xldl = QString("PASS");
        printf("合格\n");
        printf("泄露电流 = %.3fmA\n",htoi(dstr)/10000.00);
        total += 1;
    }
    else
    {
        emit MsgSignal(QString("泄露测试不合格"));
        printf("不合格\n");
        slot_stopTest();
    }


    sleep(5);
    un_char buff_result2[BUFF_MAXSIZE] = {0x7B,0x07,0x00,0x04,0x02,0x0D,0x7D};
    len = write_data(fd,buff_result2,7);
    len = 0;
    tcflush(fd,TCIFLUSH);		//处理未接收字符,用于清空输入缓冲区
    sleep(1);
    count=0;
    while(len == 0)
    {
        QString tep("交耐测试等待数据");
        emit MsgSignal(tep);
        printf("---等待数据---\n");
        len = read_data(fd,buff,BUFF_MAXSIZE);
//        sleep(1);
        count++;
        if(count >= 10)
        {
            //如果十次仍未获取到数据，退出
            break;
        }
    }

    sprintf(&c[0],"%x",buff[10] >> 4);
    sprintf(&c[1],"%x",buff[10]&0xf);
    if(c[0] == 'c' && c[1] == '1')
    {
        int i;
        char str[4];
        char dstr[5];
        for(i = 0; i < 2; ++i)
        {
            str[2*i] = buff[13+i] >> 4;
            str[2*i+1] = buff[13+i]&0xf;
        }

        sprintf(&dstr[0],"%X/n",str[2]);
        sprintf(&dstr[1],"%X/n",str[3]);
        sprintf(&dstr[2],"%X/n",str[0]);
        sprintf(&dstr[3],"%X/n",str[1]);
        dstr[4] = '\0';

        naiyaDetails = QString("交耐测试合格");
        emit MsgSignal(naiyaDetails);

        jnjg = QString("PASS");
        printf("合格\n");
        printf("交耐电流 = %.2fmA\n",htoi(dstr)/1000.00);
        total += 1;
    }
    else
    {
        emit MsgSignal(QString("交耐测试不合格"));
        printf("不合格\n");
        slot_stopTest();
    }

    un_char buff_daiji[BUFF_MAXSIZE] = {0x7B,0x07,0x00,0x02,0x00,0x09,0x7D};
    len = write_data(fd,buff_daiji,7);

    return total;
}

void workthread::receiveData(QString data)
{
    m_data = data;
}

void workthread::slot_stopTest()
{
    un_char buff_daiji[BUFF_MAXSIZE] = {0x7B,0x07,0x00,0x02,0x00,0x09,0x7D};
    write_data(m_fd,buff_daiji,7);
    emit MsgSignal(QString("测试中止"));
    this->terminate();
}

void workthread::run()
{
    //打开串口
    m_fd = init_serial();
    emit MsgSignal(QString("开始测试"));

    QString xldl = QString("FAIL");	//泄露电流
    QString jddz = QString("FAIL");	//接地电阻
    QString jnjg = QString("FAIL");  //交耐结果
    QString totalRes = QString("FAIL");//总结果

    if(test(m_fd,xldl,jddz,jnjg) == 3)
    {
        emit MsgSignal(QString("安规测试合格"));
        totalRes = QString("PASS");
    }
    else
    {
        emit MsgSignal(QString("安规测试不合格"));
    }


/**         addNewItem(const QString &testerAccount, const QString &computerSerial,
                       const QString &naiya, const QString &dianzu,const QString &loudian,
                       const QString &naiyaDetails,const QString &dianzuDetails,const QString &loudianDetails,
                       const QString &totalres);
 */
    if(ExecSQL::addNewItem(testerAccount,m_data,jnjg,jddz,xldl,naiyaDetails,dianzuDetails, loudianDetails,totalRes))
//    if(ExecSQL::addNewItem(m_data,jnjg,jddz,xldl,totalRes))
    {
        emit MsgSignal(QString("上传成功"));
    }
    else
    {
        emit MsgSignal(QString("上传失败，请重试！"));
    }
//    ExecSQL::searchAll();
    emit MsgSignal(QString("测试结束"));
    //关闭串口
    close(m_fd);
}
